64. Spring Boot Gradle插件

Spring Boot Gradle插件为Gradle提供Spring Boot支持,它允许你打包可执行jar或war存档,运行Spring Boot应用,使用spring-boot-dependencies提供的依赖管理。

64.1 包含该插件

想要使用Spring Boot Gradle插件,你只需简单的包含一个buildscript依赖,并应用spring-boot插件:

buildscript {
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.1.RELEASE")
    }
}
apply plugin: 'spring-boot'

如果使用的是一个里程碑或快照版本,你需要添加相应的repositories引用:

buildscript {
    repositories {
        maven.url "http://repo.spring.io/snapshot"
        maven.url "http://repo.spring.io/milestone"
    }
    // ...
}

64.2 Gradle依赖管理

spring-boot插件自动应用Dependency Management Plugin,并配置它导入spring-boot-starter-parent bom。这提供了跟Maven用户喜欢的相似依赖管理体验,例如,如果声明的依赖在bom中被管理的话,你就可以省略版本。为了充分使用该功能,只需要想通常那样声明依赖,但将版本号设置为空:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.thymeleaf:thymeleaf-spring4")
    compile("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
}

你声明的spring-boot Gradle插件的版本决定了spring-boot-starter-parent bom导入的版本(确保可以重复构建)。你最好将spring-boot gradle插件版本跟Spring Boot版本保持一致,版本详细信息可以在附录中查看。

spring-boot插件对于没有指定版本的依赖只会提供一个版本。如果不想使用插件提供的版本,你可以像平常那样在声明依赖的时候指定版本。例如:

dependencies {
    compile("org.thymeleaf:thymeleaf-spring4:2.1.1.RELEASE")
}

64.3 打包可执行jar和war文件

一旦spring-boot插件被应用到你的项目,它将使用bootRepackage任务自动尝试重写存档以使它们能够执行。为了构建一个jar或war,你需要按通常的方式配置项目。

你想启动的main类既可以通过一个配置选项指定,也可以通过向manifest添加一个Main-Class属性。如果你没有指定main类,该插件会搜索带有public static void main(String[] args)方法的类。

为了构建和运行一个项目artifact,你可以输入以下内容:

$ gradle build
$ java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar

为了构建一个即能执行也可以部署到外部容器的war包,你需要将内嵌容器依赖标记为providedRuntime,比如:

...
apply plugin: 'war'

war {
    baseName = 'myapp'
    version =  '0.5.0'
}

repositories {
    jcenter()
    maven { url "http://repo.spring.io/libs-snapshot" }
}

configurations {
    providedRuntime
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    ...
}

具体参考“Section 81.1, “Create a deployable war file””

64.4 就地(in-place)运行项目

为了在不先构建jar的情况下运行项目,你可以使用bootRun任务:

$ gradle bootRun

如果项目中添加了devtools,它将自动监控你的应用变动。此外,你可以运行应用,这样静态classpath资源(比如,默认位于src/main/resources下)在应用运行期间将能够重新加载,这在开发期间是非常有用的:

bootRun {
    addResources = true
}

让静态classpath资源可加载意味着bootRun不使用processResources任务的输出,例如,当使用bootRun调用时,你的应用将以未经处理的形式使用资源。

64.5 Spring Boot插件配置

Gradle插件自动扩展你的构建脚本DSL,它为脚本添加一个springBoot元素以此作为Boot插件的全局配置。你可以像配置其他Gradle扩展那样为springBoot设置相应的属性(下面有配置选项列表)。

springBoot {
    backupSource = false
}

64.6 Repackage配置

该插件添加了一个bootRepackage任务,你可以直接配置它,比如:

bootRepackage {
    mainClass = 'demo.Application'
}

下面是可用的配置选项:

名称 描述
enabled 布尔值,用于控制repackager的开关(如果你只想要Boot的其他特性而不是这个,那它就派上用场了)
mainClass 要运行的main类。如果没有指定,则使用project属性mainClassName。如果该应用插件没有使用或没有定义mainClassName,则搜索存档以寻找一个合适的类。"合适"意味着一个唯一的,具有良好格式的main()方法的类(如果找到多个则构建会失败)。你也可以通过run任务(main属性)指定main类的名称,和/或将"startScripts"(mainClassName属性)作为"springBoot"配置的替代。
classifier 添加到存档的一个文件名字段(在扩展之前),这样最初保存的存档仍旧存放在最初的位置。在存档被重新打包(repackage)的情况下,该属性默认为null。默认值适用于多数情况,但如果你想在另一个项目中使用原jar作为依赖,最好使用一个扩展来定义该可执行jar
withJarTask Jar任务的名称或值,用于定位要被repackage的存档
customConfiguration 自定义配置的名称,用于填充内嵌的lib目录(不指定该属性,你将获取所有编译和运行时依赖)
executable 布尔值标识,表示jar文件在类Unix系统上是否完整可执行,默认为false
embeddedLaunchScript 如果jar是完整可执行的,该内嵌启动脚本将添加到jar。如果没有指定,将使用Spring Boot默认的脚本
embeddedLaunchScriptProperties 启动脚本暴露的其他属性,默认脚本支持mode属性,值可以是autoservicerun
excludeDevtools 布尔值标识,表示devtools jar是否应该从重新打包的存档中排除出去,默认为false

64.7 使用Gradle自定义配置进行Repackage

有时候不打包解析自compileruntimeprovided作用域的默认依赖可能更合适些。如果创建的可执行jar被原样运行,你需要将所有的依赖内嵌进该jar中;然而,如果目的是explode一个jar文件,并手动运行main类,你可能在CLASSPATH下已经有一些可用的库了。在这种情况下,你可以使用不同的依赖集重新打包(repackage)你的jar。

使用自定义的配置将自动禁用来自compileruntimeprovided作用域的依赖解析。自定义配置即可以定义为全局的(处于springBoot部分内),也可以定义为任务级的。

task clientJar(type: Jar) {
    appendix = 'client'
    from sourceSets.main.output
    exclude('**/*Something*')
}

task clientBoot(type: BootRepackage, dependsOn: clientJar) {
    withJarTask = clientJar
    customConfiguration = "mycustomconfiguration"
}

在以上示例中,我们创建了一个新的clientJar Jar任务从你编译后的源中打包一个自定义文件集。然后我们创建一个新的clientBoot BootRepackage任务,并让它使用clientJar任务和mycustomconfiguration

configurations {
    mycustomconfiguration.exclude group: 'log4j'
}

dependencies {
    mycustomconfiguration configurations.runtime
}

BootRepackage中引用的配置是一个正常的Gradle配置。在以上示例中,我们创建了一个新的名叫mycustomconfiguration的配置,指示它来自一个runtime,并排除对log4j的依赖。如果clientBoot任务被执行,重新打包的jar将含有所有来自runtime作用域的依赖,除了log4j jars。

64.7.1 配置选项

可用的配置选项如下:

名称 描述
mainClass 可执行jar运行的main类
providedConfiguration provided配置的名称(默认为providedRuntime
backupSource 在重新打包之前,原先的存档是否备份(默认为true
customConfiguration 自定义配置的名称
layout 存档类型,对应于内部依赖是如何制定的(默认基于存档类型进行推测),具体查看available layouts
requiresUnpack 一个依赖列表(格式为"groupId:artifactId",为了运行,它们需要从fat jars中解压出来。)所有节点被打包进胖jar,但运行的时候它们将被自动解压

64.7.2 可用的layouts

layout属性用于配置存档格式及启动加载器是否包含,以下为可用的layouts:

名称 描述 可执行
JAR 常规的可执行JAR layout
WAR 可执行WAR layoutprovided依赖放置到WEB-INF/lib-provided,以免war部署到servlet容器时造成冲突
ZIP(别名DIR JAR layout类似,使用PropertiesLauncher
MODULE 捆绑(Bundle)依赖(排除那些provided作用域的依赖)和项目资源
NONE 捆绑(Bundle)所有依赖和项目资源
### 64.8 理解Gradle插件是如何工作的

spring-boot应用到你的Gradle项目,一个默认的名叫bootRepackage的任务被自动创建。bootRepackage任务依赖于Gradle assemble任务,当执行时,它会尝试找到所有限定符为空的jar artifacts(也就是说,tests和sources jars被自动跳过)。

由于bootRepackage会查找'所有'创建的jar artifacts,Gradle任务执行的顺序就非常重要了。多数项目只创建一个单一的jar文件,所以通常这不是一个问题。然而,如果你正打算创建一个更复杂的,使用自定义jarBootRepackage任务的项目setup,有几个方面需要考虑。

如果'仅仅'从项目创建自定义jar文件,你可以简单地禁用默认的jarbootRepackage任务:

jar.enabled = false
bootRepackage.enabled = false

另一个选项是指示默认的bootRepackage任务只能使用一个默认的jar任务:

bootRepackage.withJarTask = jar

如果你有一个默认的项目setup,在该项目中,主(main)jar文件被创建和重新打包。并且,你仍旧想创建额外的自定义jars,你可以将自定义的repackage任务结合起来,然后使用dependsOn,这样bootJars任务就会在默认的bootRepackage任务执行以后运行:

task bootJars
bootJars.dependsOn = [clientBoot1,clientBoot2,clientBoot3]
build.dependsOn(bootJars)

上面所有方面经常用于避免一个已经创建的boot jar又被重新打包的情况。重新打包一个存在的boot jar不是什么大问题,但你可能会发现它包含不必要的依赖。

64.9 使用Gradle将artifacts发布到Maven仓库

如果声明依赖但没有指定版本,且想要将artifacts发布到一个Maven仓库,那你需要使用详细的Spring Boot依赖管理来配置Maven发布。通过配置它发布继承自spring-boot-starter-parent的poms或引入来自spring-boot-dependencies的依赖管理可以实现该需求。这种配置的具体细节取决于你如何使用Gradle及如何发布该artifacts。

64.9.1 自定义Gradle,用于产生一个继承依赖管理的pom

下面示例展示了如何配置Gradle去产生一个继承自spring-boot-starter-parent的pom,更多信息请参考Gradle用户指南

uploadArchives {
    repositories {
        mavenDeployer {
            pom {
                project {
                    parent {
                        groupId "org.springframework.boot"
                        artifactId "spring-boot-starter-parent"
                        version "1.4.1.RELEASE"
                    }
                }
            }
        }
    }
}

64.9.2 自定义Gradle,用于产生一个导入依赖管理的pom

以下示例展示了如何配置Gradle产生一个导入spring-boot-dependencies提供的依赖管理的pom,更多信息请参考Gradle用户指南

uploadArchives {
    repositories {
        mavenDeployer {
            pom {
                project {
                    dependencyManagement {
                        dependencies {
                            dependency {
                                groupId "org.springframework.boot"
                                artifactId "spring-boot-dependencies"
                                version "1.4.1.RELEASE"
                                type "pom"
                                scope "import"
                            }
                        }
                    }
                }
            }
        }
    }
}